package binarys

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"github.com/sirupsen/logrus"
	"go-iot-gateway/internal/apk/maths"
	"math"
	"strconv"
	"strings"
)

const (
	BYTE_FORMAT_12   = "12"   // 大端[默认]
	BYTE_FORMAT_1234 = "1234" // 大端[默认]
	BYTE_FORMAT_21   = "21"   //小端
	BYTE_FORMAT_4321 = "4321" //小端

	BYTE_FORMAT_2143 = "2143"
	BYTE_FORMAT_3412 = "3412"
)

// TurnBit 位数截取
func TurnBit(bytes []byte, begin uint64, end uint64) uint64 {
	if bytes == nil || begin > end {
		return 0
	}

	bLen := len(bytes)
	if bLen <= 0 {
		return 0
	}

	//最多取64位
	if bLen > 8 {
		bytes = bytes[:8]
		bLen = 8
	}

	maxLen := uint64(bLen*8) - 1

	if begin > maxLen {
		return 0
	}

	//截取范围超出,取最后一个
	if end > maxLen {
		end = maxLen
	}

	binaryString := BinaryString(bytes)
	parseUint, err := strconv.ParseUint(binaryString[begin:end+1], 2, 64)
	if err != nil {
		logrus.Errorf("TurnBit 截取异常 % x  begin: %d  end: %d", bytes, begin, end)
		return 0
	}
	return parseUint
}

// MapBit 位数截取,保持地址位不变
func MapBit(bytes []byte, begin uint64, end uint64) []byte {

	if bytes == nil || begin > end {
		return []byte{}
	}

	bLen := len(bytes)
	if bLen <= 0 {
		return []byte{}
	}

	maxLen := uint64(bLen*8) - 1

	if begin > maxLen {
		return []byte{}
	}

	//截取范围超出,取最后一个
	if end > maxLen {
		end = maxLen
	}

	byteBegin := begin / 8
	byteEnd := end/8 + 1
	if byteEnd > uint64(bLen) {
		byteEnd = uint64(bLen)
	}

	subByte := bytes[byteBegin:byteEnd]

	//todo 不应该改变  bytes 的值
	beginOffset := begin % 8
	if beginOffset != 0 {
		subByte[0] = subByte[0] & (0xff >> beginOffset)
	}

	endOffset := (end + 1) % 8
	if endOffset != 0 {
		f := 8 - endOffset
		i := maths.MinUint64(byteEnd, uint64(len(subByte))) - 1
		subByte[i] = subByte[i] >> f
	}

	return subByte
}

func PrintBinaryString(data []byte) string {
	var result string
	for _, b := range data {
		// 将byte转换为二进制字符串，并确保每个byte都是8位
		binaryString := strconv.FormatInt(int64(b), 2)
		// 如果不足8位，前面补0
		if len(binaryString) < 8 {
			binaryString = fmt.Sprintf("%08s", binaryString)
		}
		result += binaryString + " "
	}
	return strings.TrimSpace(result)
}

func BinaryString(data []byte) string {
	var result string
	for _, b := range data {
		// 将byte转换为二进制字符串，并确保每个byte都是8位
		binaryString := strconv.FormatInt(int64(b), 2)
		// 如果不足8位，前面补0
		if len(binaryString) < 8 {
			binaryString = fmt.Sprintf("%08s", binaryString)
		}
		result += binaryString
	}
	return result
}

func BytesToInt642(bytes []byte) int64 {
	val := int64(0)
	if bytes == nil {
		return val
	}
	l := len(bytes)
	if l == 0 {
		return 0
	}
	isMinus := bytes[0] >> 7
	if isMinus == 1 { //
		for i := 0; i < l; i++ {
			val = val | int64(^bytes[i])<<(8*(l-i-1))
		}
		return (val + 1) * -1
	} else {
		for i := 0; i < l; i++ {
			val = val | int64(bytes[i])<<(8*(l-i-1))
		}
		return val
	}
}

func BytesToUint642(bytes []byte) uint64 {
	val := uint64(0)
	if bytes == nil {
		return val
	}
	l := len(bytes)
	if l == 0 {
		return 0
	}

	for i := 0; i < l; i++ {
		val = val | uint64(bytes[i])<<(8*(l-i-1))
	}
	return val

}

func BytesToInt64(bytes []byte, format string) int64 {
	bytes = RankBytes1234(bytes, format)
	return BytesToInt642(bytes)
}

func BytesToUint64(bytes []byte, format string) uint64 {
	bytes = RankBytes1234(bytes, format)
	return BytesToUint642(bytes)
}

//
//func BytesToFloat32(bytes []byte, format string) float32 {
//	return 0
//}

func BytesToFloat642(bytes []byte) float64 {
	if bytes == nil {
		return 0
	}
	l := len(bytes)
	switch l {
	case 0:
		return 0
	case 2:
		bits := toUint16(bytes)
		return float64(math.Float32frombits(uint32(bits)))
	case 4:
		bits := binary.BigEndian.Uint32(bytes)
		return float64(math.Float32frombits(bits))
	case 8:
		bits := binary.BigEndian.Uint64(bytes)
		return math.Float64frombits(bits)
	}
	logrus.Error(bytes, "无法转换成 float64")
	return 0
}

func BytesToFloat64(bytes []byte, format string) float64 {
	bytes = RankBytes1234(bytes, format)
	return BytesToFloat642(bytes)
}

func toUint16(b []byte) uint16 {
	_ = b[1]
	return uint16(b[1]) | uint16(b[0])<<8
}

func BytesToString(bytes []byte) string {
	return string(bytes)
}

func RankBytes1234(bs []byte, format string) []byte {

	if bs == nil {
		return bs
	}
	byteLen := len(bs)
	if byteLen <= 1 {
		return bs
	}
	//BYTE_FORMAT_12, BYTE_FORMAT_1234: 正常顺序不处理
	bytes := make([]byte, byteLen, byteLen)
	copy(bytes, bs)
	if format == BYTE_FORMAT_4321 || format == BYTE_FORMAT_3412 {
		for i := 0; i < byteLen/2; i++ {
			bytes[i] = bytes[i] ^ bytes[byteLen-i-1]
			bytes[byteLen-i-1] = bytes[i] ^ bytes[byteLen-i-1]
			bytes[i] = bytes[i] ^ bytes[byteLen-i-1]
		}
		if format == BYTE_FORMAT_4321 {
			return bytes
		}
	}
	//todo 如果byte 长于 4个，也需要调用 1
	switch format {
	case BYTE_FORMAT_21, BYTE_FORMAT_2143, BYTE_FORMAT_3412:
		for i := 0; i < byteLen; i = i + 2 {
			bytes[i] = bytes[i] ^ bytes[i+1]
			bytes[i+1] = bytes[i] ^ bytes[i+1]
			bytes[i] = bytes[i] ^ bytes[i+1]
		}
		return bytes
	}
	return bytes
}

func Uint64ToBytes(val uint64, order binary.ByteOrder) ([]byte, error) {
	buf := new(bytes.Buffer)
	err := binary.Write(buf, order, val)
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}

func Int64ToBytes(val int64, order binary.ByteOrder) ([]byte, error) {
	buf := new(bytes.Buffer)
	err := binary.Write(buf, order, val)
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}

func Float64ToBytes(val float64, order binary.ByteOrder) ([]byte, error) {
	buf := new(bytes.Buffer)
	err := binary.Write(buf, order, val)
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}
